#include "srgplocal.h"

#define __CURATT(xx)	srgp__curActiveCanvasSpec.attributes.xx

#ifdef _Windows

static int writemode_table[4] = {
	/* REPLACE */	R2_COPYPEN,
	/* XOR     */	R2_NOT,
	/* OR	   */	R2_MERGEPEN,
	/* AND	   */	R2_MASKPEN
};

#endif


void
SRGP_setWriteMode (writeMode value)
{

   if (value == __CURATT(write_mode)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setWriteMode  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_write_mode(value);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.write_mode = value;

#ifdef _Windows
    {
	HDC hdc;

	hdc = GetDC (srgp__canvasTable[0].drawable.win);
	SetROP2(hdc, writemode_table[value]);
	ReleaseDC(srgp__canvasTable[0].drawable.win, hdc);
    }
#endif

}

void
SRGP_setClipRectangle (rectangle rect)
{
#ifdef _Windows
	HDC hdc;
	HRGN hRgn;
#endif

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setClipRect  (%d,%d)->(%d,%d)\n", ExplodeRect(rect));
	  srgp_check_system_state();
	  srgp_check_rectangle
	 (rect.bottom_left.x, rect.bottom_left.y,
	  rect.top_right.x, rect.top_right.y);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.clip_rectangle = rect;

#ifdef _Windows
	hdc = GetDC (srgp__canvasTable[0].drawable.win);
	hRgn = CreateRectRgn(rect.bottom_left.x, FIXED(rect.top_right.y),
						 rect.top_right.x+1, FIXED(rect.bottom_left.y)+1);
	SelectClipRgn(hdc, hRgn);
	DeleteObject(hRgn);
	ReleaseDC(srgp__canvasTable[0].drawable.win, hdc);

#endif
}



/** FILL STYLE
Only the fill GC is to be modified.
The SRGP fill-style maps directly to X's fill-style.
**/
void
SRGP_setFillStyle (drawStyle value)
{
   if (value == __CURATT(fill_style)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setFillStyle  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_fill_style(value);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.fill_style = value;
}

/*!*/
void
SRGP_setFillBitmapPattern (int value)
{
   if (value == __CURATT(fill_bitmap_pattern_id)) return;

   DEBUG_AIDS{
      SRGP_trace (SRGP_logStream, "SRGP_setFillBitmapPattern  %d\n", value);
	  srgp_check_system_state();
      srgp_check_pattern_index(value);
      srgp_check_pattern_table_entry(srgp__bitmapPatternTable[value]);
      LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.fill_bitmap_pattern_id = value;
}

/*!*/
void
SRGP_setFillPixmapPattern (int value)
{
   if (value == __CURATT(fill_pixmap_pattern_id)) return;
      
   DEBUG_AIDS{
      SRGP_trace (SRGP_logStream, "SRGP_setFillPixmapPattern  %d\n", value);
	  srgp_check_system_state();
      srgp_check_pattern_index(value);
	  srgp_check_pattern_table_entry(srgp__pixmapPatternTable[value]);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.fill_pixmap_pattern_id = value;

} 

/** PEN STYLE
X11 implementation:
   Only the frame GC is to be modified.
   The SRGP pen-style maps directly to X's fill-style.
**/

void
SRGP_setPenStyle (drawStyle value)
{
   if (value == __CURATT(pen_style)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setPenStyle  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_fill_style(value);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.pen_style = value;
}

/*!*/
void
SRGP_setPenBitmapPattern (int value)
{
   if (value == __CURATT(pen_bitmap_pattern_id)) return;

   DEBUG_AIDS{
      SRGP_trace (SRGP_logStream, "SRGP_setPenBitmapPattern  %d\n", value);
	  srgp_check_system_state();
      srgp_check_pattern_index(value);
      srgp_check_pattern_table_entry(srgp__bitmapPatternTable[value]);
      LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.pen_bitmap_pattern_id = value;

}

/*!*/
void
SRGP_setPenPixmapPattern (int value)
{
   if (value == __CURATT(pen_pixmap_pattern_id)) return;

   DEBUG_AIDS{
      SRGP_trace (SRGP_logStream, "SRGP_setPenPixmapPattern  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_pattern_index(value);
      srgp_check_pattern_table_entry(srgp__pixmapPatternTable[value]);
      LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.pen_pixmap_pattern_id = value;

}






/** MARKER ATTRIBUTES
**/

void 
SRGP_setMarkerSize (int value)
{
   if (value == __CURATT(marker_size)) return;

   DEBUG_AIDS{
      SRGP_trace (SRGP_logStream, "SRGP_setMarkerSize  %d\n", value);
	  srgp_check_system_state();
      srgp_check_marker_size(value);
      LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.marker_size = value;
}


void 
SRGP_setMarkerStyle (markerStyle value)
{
   if (value == __CURATT(marker_style)) return;

   DEBUG_AIDS{
      SRGP_trace (SRGP_logStream, "SRGP_setMarkerStyle  %d\n", value);
	  srgp_check_system_state();
      srgp_check_marker_style(value);
      LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.marker_style = value;
}

/*!*/
void
SRGP_setLineStyle (lineStyle value)
{
   if (value == __CURATT(line_style)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setLineStyle  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_line_style(value);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.line_style = value;

}

/*!*/
void
SRGP_setLineWidth (int value)
{
#ifdef _Windows
	HDC    hdc;
	int    colorIndex;
#endif
   if (value == __CURATT(line_width)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setLineWidth  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_line_width(value);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.line_width = value;

#ifdef _Windows
	colorIndex = srgp__curActiveCanvasSpec.attributes.color;
	if (colorIndex < 0)
		colorIndex = 0;
	hdc = GetDC (srgp__canvasTable[0].drawable.win);
	DeleteObject (SelectObject (hdc,
				  CreatePen(PS_INSIDEFRAME, value,
				  color_table[srgp__curActiveCanvasSpec.attributes.color])));
	ReleaseDC(srgp__canvasTable[0].drawable.win, hdc);
#endif

}





/** ATTRIBUTES RELATED TO COLOR
**/

void
SRGP_setPlaneMask (int value)
{
   if (value == __CURATT(plane_mask)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setPlaneMask  %d\n", value);
	  srgp_check_system_state();
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.plane_mask = value;

}


void
SRGP_setColor (int value)
{

   if (value == __CURATT(color)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setColor  %d\n", value);
	  srgp_check_system_state();
	  SRGP_correct_color(value);
	  LeaveIfNonFatalErr();
   }

   if (value > srgp__max_pixel_value)
	  value = srgp__max_pixel_value;
   srgp__curActiveCanvasSpec.attributes.color = value;

#ifdef _Windows
   {
   HDC   hdc;
   int   lineWidth;

	lineWidth = srgp__curActiveCanvasSpec.attributes.line_width;
	if (lineWidth < 0)
		lineWidth = 0;
	hdc = GetDC (srgp__canvasTable[0].drawable.win);
	DeleteObject (SelectObject (hdc,
				  CreatePen(PS_INSIDEFRAME,
							srgp__curActiveCanvasSpec.attributes.line_width,
							color_table[value])));

	if (srgp__curActiveCanvasSpec.attributes.fill_style == SOLID)
		DeleteObject (SelectObject (hdc,
									CreateSolidBrush(color_table[value])));

	SetTextColor (hdc, color_table[value]);
	ReleaseDC(srgp__canvasTable[0].drawable.win, hdc);
   }
#endif
}



void
SRGP_setBackgroundColor (int value)
{
   if (value == __CURATT(background_color)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setBackgroundColor  %d\n", value);
	  srgp_check_system_state();
	  SRGP_correct_color(value);
	  LeaveIfNonFatalErr();
   }

   if (value > srgp__max_pixel_value)
	  value = srgp__max_pixel_value;
   srgp__curActiveCanvasSpec.attributes.background_color = value;

#ifdef _Windows
{
	HDC hdc;

	hdc = GetDC (srgp__canvasTable[0].drawable.win);
	SetBkColor (hdc, color_table[value]);
	ReleaseDC(srgp__canvasTable[0].drawable.win, hdc);
}
#endif

}

#ifndef _Windows

/*
	Should be contained in color.c  (and is for the Windows version)
*/

/** Load Single Color
A convenience subroutine for setting a single color table entry
**/
void SRGP_loadSingleColor
   (int startentry,
	unsigned short redi,
	unsigned short greeni,
	unsigned short bluei)
{
   PUSH_TRACE;
   SRGP_loadColorTable (startentry, 1, &redi, &greeni, &bluei);
   POP_TRACE;
}

#endif


/** FONT
The frame gc is used to draw text.  This is a cheat, and violates SRGP's
spec.  This will be fixed someday.
**/
void
SRGP_setFont (int value)
{
   if (value == __CURATT(font)) return;

   DEBUG_AIDS{
	  SRGP_trace (SRGP_logStream, "SRGP_setFont  %d\n", value);
	  srgp_check_system_state();
	  srgp_check_extant_font(value);
	  LeaveIfNonFatalErr();
   }

   srgp__curActiveCanvasSpec.attributes.font = value;

#ifdef _Windows
{
	HDC hdc;

	hdc = GetDC (srgp__canvasTable[0].drawable.win);
    /* Don't delete old font objects.  They can still be used */
	SelectObject (hdc, srgp__fontTable[value]);
	ReleaseDC(srgp__canvasTable[0].drawable.win, hdc);
}
#endif

}



/** BATCH SET ATTRIBUTES
Woefully inefficient, but at least I don't reset attributes whose
value has not changed.
**/

void
SRGP_setAttributes (attribute_group *att_group)
{
   SRGP_trace (SRGP_logStream, "SRGP_setAttributes 0x%d\n", att_group);
   PUSH_TRACE;
   SRGP_setWriteMode (att_group->write_mode);
   SRGP_setClipRectangle (att_group->clip_rectangle);

   SRGP_setFont (att_group->font);
   SRGP_setLineStyle (att_group->line_style);
   SRGP_setLineWidth (att_group->line_width);
   SRGP_setColor (att_group->color);
   SRGP_setPlaneMask (att_group->plane_mask);
   SRGP_setBackgroundColor (att_group->background_color);
   SRGP_setFillStyle (att_group->fill_style);
   SRGP_setFillPixmapPattern (att_group->fill_pixmap_pattern_id);
   SRGP_setFillBitmapPattern (att_group->fill_bitmap_pattern_id);
   SRGP_setPenStyle (att_group->pen_style);
   SRGP_setPenPixmapPattern (att_group->pen_pixmap_pattern_id);
   SRGP_setPenBitmapPattern (att_group->pen_bitmap_pattern_id);
   SRGP_setMarkerSize (att_group->marker_size);
   SRGP_setMarkerStyle (att_group->marker_style);
   POP_TRACE;
}
